import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_base_plugin/base_library/base_network/x_api.dart';
import 'package:flutter_base_plugin/flutter_base_plugin.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';

import '../../base_network/bean/http_error_bean.dart';
import '../../base_utils/log_utils.dart';
import './base_view_model.dart';
import '../../base_const/constants.dart';

abstract class BaseRefreshViewModel<T> extends BaseViewModel {
  ///进入页面时（首次）调用接口是否成功
  bool _isLoadingSuccess = false;

  ///加载更多（分页加载）调用接口是否成功
  bool _isLoadingMoreSuccess = false;

  ///当前请求是否是下拉刷新
  bool _isLoadingForPullRefresh = false;

  ///当前请求是否是加载更多
  bool _isLoadingForLoadMore = false;

  ///数据源:针对列表请求，获取的数据
  List<T> dataList = [];

  ///分页加载初始index
  late int _initPageIndex = 1;

  ///分页页数
  late int _pageNum;

  ///分页加载：能否加载更多
  bool _canLoadMore = false;

  ///下拉刷新完成提示
  String? _refreshedText = '刷新完成';

  ///每页请求数据个数,用于分页加载
  late int _pageSize = 10;

  RefreshController refreshController = RefreshController(initialRefresh: true);
  final EasyRefreshController _controller = EasyRefreshController();

  EasyRefreshController get controller => _controller;

  BaseRefreshViewModel({int? initPageIndex, int? pageSize}) : super() {
    _pageNum = _initPageIndex;
    _pageSize = pageSize ?? configPageSize();
  }

  int get pageNum => _pageNum;

  int get pageSize => _pageSize;

  String? get refreshedText => _refreshedText;

  bool get canLoadMore => _canLoadMore;

  ///进入页面时onLoading方法请求的List数据分页加载时，起始页Index
  ///子类根据需要可以选择在构造传入或重写该方法
  ///_isRequestListData=true并且_isPageLoad=true 时，该方法才有效
  int configInitPageIndex() {
    return Constants.initPageIndex;
  }

  ///进入页面时onLoading方法请求的List数据分页加载时，页大小
  ///子类根据需要可以选择在构造传入或重写该方法
  ///_isRequestListData=true并且_isPageLoad=true 时，该方法才有效
  int configPageSize() {
    return Constants.pageSize;
  }

  ///配置当前请求Options
  ///子类根据需要可以重写该方法
  // Options? configHttpOptions() {
  //   return null;
  // }

  ///配置下拉刷新失败时，是否显示失败的占位View
  ///场景：数据请求成功过，但是在下拉刷新时失败了，此时是否显示失败页
  ///true：显示失败页面
  ///false: 不显示失败页面，继续显示之前请求成功过的数据页面
  ///子类根据需要可以重写该方法
  bool configIsPullRefreshFailShowFailView() {
    return false;
  }

  ///配置加载更多（分页加载）失败时，是否显示失败的占位View
  ///场景：数据请求成功过，但是在加载更多时失败了，此时是否显示失败页
  ///true：显示失败页面
  ///false: 不显示失败页面，继续显示之前请求成功过的数据页面
  ///子类根据需要可以重写该方法
  bool configIsLoadMoreFailShowFailView() {
    return false;
  }

  ///请求失败是否显示Toast提示错误信息
  ///子类根据需求重写
  ///[isLoadMore] 是否是加载更多时，回调的该方法
  bool configIsShowFailToast(bool isLoadMore) {
    return true;
  }

  ///分页加载完所有数据时回调
  ///子类根据需求重写
  void onLoadCompleteAllCallback() {
    ToastUtils.show("已加载完全部");
  }

  ///请求失败回调,子类根据需求重写
  ///[errorBean] http失败响应对象
  ///[isLoadMoreFailCallback] 是否是加载更多失败时回调
  void onHttpErrorCallback(HttpErrorBean errorBean,
      {bool isLoadMoreFailCallback = false}) {}

  ///************************根据需求，可选择重写上面方法***************************

  ///************************下面是必须重写的方法***************************
  ///获取http请求参数
  Map<String, dynamic> getRequestParams();

  ///获取http请求url
  String getUrl();

  ///设置能否加载更多
  void setCanLoadMore(bool value) {
    _canLoadMore = value;
  }

  ///加载数据
  ///第一次请求或下拉刷新时调用(请求参数设置为初始值)
  @override
  Future onLoading() async {
    LogUtils.i(getTag(), 'onLoading');
    if (isLoading) {
      LogUtils.d(getTag(), 'onLoading() is Loading');
      return;
    }
    isLoading = true;
    _refreshedText = '刷新成功';

    CancelToken cancelToken = CancelToken();
    cancelTokenList.add(cancelToken);

    ///保存当前分页加载pageNum，当下拉刷新失败时，恢复之前的pageNum
    _isLoadingForPullRefresh = true;

    ///请求失败回调
    var onError = (HttpErrorBean errorBean) {
      ///当下拉刷新失败时，恢复之前的pageNum
      isLoading = false;

      ///下拉刷新请求失败，并且设置显示FailView，此时清除之前获取的数据
      if (_isLoadingForPullRefresh && configIsPullRefreshFailShowFailView()) {
        dataList.clear();
      }
      _isLoadingSuccess = false;
      _refreshedText = '刷新失败';
      controller.finishRefresh(success: false);
      refreshController.refreshFailed();
      onHttpErrorCallback(errorBean);
      // notifyListeners();
    };

    ///请求完成回调
    var onComplete = () {
      isLoading = false;
      cancelTokenList.remove(cancelToken);
    };

    ///下拉刷新或第一次加载时
    _pageNum = _initPageIndex;

    ///请求列表数据
    await api.requestList<T>(
      getUrl(),
      Method.GET,
      params: getRequestParams(),
      // option: configHttpOptions()??,
      isShowLoading: false,
      isShowFailToast: configIsShowFailToast(false),
      cancelToken: cancelToken,
      onError: onError,
      onComplete: onComplete,
      onSuccess: (List<T>? list) {
        isLoading = false;
        ///请求成功回
        _isLoadingSuccess = true;
        dataList = [];
        list = list ?? [];
        dataList.addAll(list);
        // refreshController.refreshCompleted();
        controller.finishRefresh();
        refreshController.refreshCompleted();
        // notifyListeners();
        ///list分页加载
        if (list.length < _pageSize) {
          _canLoadMore = false;
          // 小于分页的数量,禁止上拉加载更多
          refreshController.loadNoData();
          controller.finishLoad(noMore: true);
        } else {
          //防止上次上拉加载更多失败,需要重置状态
          refreshController.loadComplete();
          controller.finishRefresh();
          _canLoadMore = true;
          _pageNum++;
        }
      },
    );
  }

  ///加载更多:针对分页加载
  Future onLoadingMore() async {
    LogUtils.i(getTag(), 'onLoadMore:$_canLoadMore');
    if (_canLoadMore) {
      if (isLoading) {
        LogUtils.d(getTag(), 'onLoadMore is Loading');
        return;
      }
      _isLoadingForLoadMore = true;
      isLoading = true;
      CancelToken cancelToken = CancelToken();
      cancelTokenList.add(cancelToken);
      await api.requestList<T>(
        getUrl(),
        Method.GET,
        params: getRequestParams(),
        // option: configHttpOptions(),
        isShowLoading: false,
        isShowFailToast: configIsShowFailToast(true),
        onSuccess: (List<T>? list) {
          ///请求成功回调
          _isLoadingMoreSuccess = true;
          isLoading = false;
          if (list!.isEmpty) {
            _pageNum--;
            refreshController.loadNoData();
            controller.finishLoad(noMore: true);
          } else {
            dataList.addAll(list);
            ///list分页加载
            if (list.length < _pageSize) {
              _canLoadMore = false;
              // 小于分页的数量,禁止上拉加载更多
              refreshController.loadNoData();
              controller.finishLoad(noMore: true);
            } else {
              //防止上次上拉加载更多失败,需要重置状态
              // refreshController.loadComplete();
              controller.finishLoad();
              _canLoadMore = true;
              _pageNum++;
            }
          }
        },
        onError: (HttpErrorBean errorBean) {
          _isLoadingMoreSuccess = false;
          _pageNum--;
          isLoading = false;
          ///列表加载更多请求失败，并且设置显示FailView，此时清除之前获取的数据
          if (configIsLoadMoreFailShowFailView()) {
            dataList = [];
          }
          refreshController.loadFailed();
          controller.finishLoad(success: false);

          ///请求失败回调
          onHttpErrorCallback(errorBean, isLoadMoreFailCallback: true);
          error = errorBean;
        },
        onComplete: () {
          ///请求完成回调
          isLoading = false;
          cancelTokenList.remove(cancelToken);
        },
      );
    } else {
      onLoadCompleteAllCallback();
    }
  }

  ///手动下拉刷新
  Future onPullToRefresh() async {
    _isLoadingForPullRefresh = true;
    await onLoading();
  }

  ///请求是否成功
  @override
  bool isSuccess() {
    if (_isLoadingSuccess ||
        _isLoadingMoreSuccess ||
        (_isLoadingForPullRefresh && !configIsPullRefreshFailShowFailView()) ||
        (_isLoadingForLoadMore && !configIsLoadMoreFailShowFailView())) {
      _isLoadingForPullRefresh = false;
      _isLoadingForLoadMore = false;

      return dataList != null && dataList.length > 0;
    } else {
      _isLoadingForPullRefresh = false;
      _isLoadingForLoadMore = false;
      return false;
    }
  }

  ///请求是否失败
  @override
  bool isFail() {
    return !_isLoadingSuccess && !_isLoadingMoreSuccess;
  }

  ///请求数据是否为空
  @override
  bool isEmpty() {
    return dataList == null || dataList.isEmpty;
  }
}
